public class Test {
    Counter counter = new Counter();

    public static void main(String[] args) throws Exception {
        new Test().execute();
    }

    public void execute() throws Exception {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                counter.add(1);
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                counter.dec(1);
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println("Final count: " + counter.get());
    }
}

class Counter {
    private int count = 0;

    // 线程调用add()、dec()方法时
    // synchronized锁住的对象是this，即当前实例，这又使得创建多个Counter实例的时候，它们之间互不影响，可以并发执行
    public void add(int n) {
        synchronized (this) {
            count += n;
        }
    }

    // synchronized (this) 锁的简写形式，等同于上面的add()方法
    public synchronized void add_sync(int n) {
        count += n;
    }

    public void dec(int n) {
        synchronized (this) {
            count -= n;
        }
    }

    public int get() {
        return count;
    }

    // synchronized(Counter.class) 锁的是 Counter 类的 Class 对象，
    // 这使得无论创建多少个 Counter 实例，调用 staticMethod() 方法时，都会锁住同一个 Class 对象，从而实现跨实例的同步
    static synchronized void staticMethod() {
        // 锁的是 Counter.class 对象
    }
}